#include <iostream>
#include <sstream>
#include <time.h>
#include <stdio.h>

#include "mv_pub.hpp"

using namespace std;

#define HGUI_DEBUG

// 求放大后的矩形座标(p00,p01,p10,p11)
void MvPub::calRectangle(InputArray inPts, float calX, float calY, OutputArray outPts) {
	Mat mtPts = inPts.getMat();

	Point2f s00, s01, s10, s11;

	outPts.create(Size(4, 1), CV_32FC2);
	Point2f *vo = (Point2f *) outPts.getMat().data;

	s00 = mtPts.at<Point2f>(0, 0);
	s01 = mtPts.at<Point2f>(0, 1);
	s10 = mtPts.at<Point2f>(0, 2);
	s11 = mtPts.at<Point2f>(0, 3);

	vo[0].x = (s00.x + s01.x) / 2 + (s00.x - s01.x) / 2 * calX;
	vo[1].x = (s00.x + s01.x) / 2 - (s00.x - s01.x) / 2 * calX;
	vo[2].x = vo[0].x;
	vo[3].x = vo[1].x;

	vo[0].y = (s00.y + s10.y) / 2 + (s00.y - s10.y) / 2 * calY;
	vo[1].y = vo[0].y;
	vo[2].y = (s00.y + s10.y) / 2 - (s00.y - s10.y) / 2 * calY;
	vo[3].y = vo[2].y;
}

float MvPub::calDistance(Point2f p0, Point2f p1) {
	return sqrt((p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y));
}

void MvPub::calDistances(InputArray p, OutputArray o) {

	Mat ps = p.getMat();
	int num = ps.size().width * ps.size().height;

	Mat tmp(num, num, CV_32FC1);
	for (int i = 0; i < num; i++) {
		for (int j = 0; j < num; j++) {
			tmp.at<float>(i, j) = calDistance(ps.at<Point2f>(i), ps.at<Point2f>(j));
		}
	}

	cv::sort(tmp, tmp, CV_SORT_EVERY_ROW + CV_SORT_ASCENDING);
	for (int i = 0; i < num; i++) {
		Scalar avg = cv::sum(tmp.row(i));
		tmp.at<float>(i, 0) = avg.val[0] / (num - 1);
	}

	tmp.copyTo(o);
}

float MvPub::calAngle(Point2f p0, Point2f p1) {
	float y = p1.y - p0.y, x = p1.x - p0.x;
	return fastAtan2(y, x);
}

void MvPub::calAngles(InputArray p, OutputArray o) {

	Mat ps = p.getMat();
	int num = ps.size().width * ps.size().height;

	Mat tmp(num, num, CV_32FC1);
	for (int i = 0; i < num; i++) {
		for (int j = 0; j < num; j++) {
			tmp.at<float>(i, j) = calAngle(ps.at<Point2f>(i), ps.at<Point2f>(j));
		}
	}

	cv::sort(tmp, tmp, CV_SORT_EVERY_ROW + CV_SORT_ASCENDING);

	tmp.copyTo(o);
}

void MvPub::rotatePoints(InputArray inPts, Point2f center, float angle, OutputArray outPts) {

	angle = angle * CV_PI / 180.0;

	int row = inPts.size().height, col = inPts.size().width;
	Point2f *inPt = (Point2f*) inPts.getMat().data;

	Mat tmp(row, col, CV_32FC2, Scalar(0, 0));
	Point2f *outPt = (Point2f*) tmp.data;

	for (int i = 0; i < row * col; i++) {
		outPt->x = cos(angle) * (inPt->x - center.x) - sin(angle) * (inPt->y - center.y) + center.x;
		outPt->y = sin(angle) * (inPt->x - center.x) + cos(angle) * (inPt->y - center.y) + center.y;
		outPt++;
		inPt++;
	}

	tmp.copyTo(outPts);
}

void MvPub::movePoints(InputArray inPts, Point2f offset, OutputArray outPts) {

	int row = inPts.size().height, col = inPts.size().width;
	Point2f *inPt = (Point2f*) inPts.getMat().data;

	Mat tmp(row, col, CV_32FC2, Scalar(0, 0));
	Point2f *outPt = (Point2f*) tmp.data;

	for (int i = 0; i < row * col; i++) {
		outPt->x = inPt->x + offset.x;
		outPt->y = inPt->y + offset.y;

		outPt++;
		inPt++;
	}

	tmp.copyTo(outPts);
}

void MvPub::drawXLine(Mat& src, Point2f &pt, Scalar sclr, int width, int len) {
	Point up, down, left, right;

	up = down = left = right = pt;

	up.y = up.y - len;
	down.y = down.y + len;
	left.x = left.x - len;
	right.x = right.x + len;

	line(src, up, down, sclr, width);
	line(src, left, right, sclr, width);
}

// 生成7x7十字模板(粗线)
void MvPub::makeTemp7x7Strong(OutputArray temp) {
	Mat m(7, 7, CV_8UC1, Scalar(0));

	m.col(2).setTo(Scalar(1));
	m.col(3).setTo(Scalar(1));
	m.col(4).setTo(Scalar(1));

	m.row(2).setTo(Scalar(1));
	m.row(3).setTo(Scalar(1));
	m.row(4).setTo(Scalar(1));

	m.copyTo(temp);
}

// 生成7x7粗反向十字模板
void MvPub::makeTemp7x7StrongInv(OutputArray temp) {
	Mat m(7, 7, CV_8UC1, Scalar(1));

	m.col(2).setTo(Scalar(0));
	m.col(3).setTo(Scalar(0));
	m.col(4).setTo(Scalar(0));

	m.row(2).setTo(Scalar(0));
	m.row(3).setTo(Scalar(0));
	m.row(4).setTo(Scalar(0));

	m.copyTo(temp);
}

Mat MvPub::makeTempX(int x, int y) {

	if (x == 0 || y == 0) {
		x = 3;
		y = 3;
	}

	Mat tempx(y, x, CV_8UC1, Scalar(255));

	tempx.col(x / 2).setTo(Scalar(0));
	tempx.row(y / 2).setTo(Scalar(0));

	return tempx;
}

Mat MvPub::makeInvTempX(int x, int y) {

	if (x == 0 || y == 0) {
		x = 3;
		y = 3;
	}

	Mat tempx(y, x, CV_8UC1, Scalar(0));

	tempx.col(x / 2).setTo(Scalar(255));
	tempx.row(y / 2).setTo(Scalar(255));

	return tempx;
}

void MvPub::mirrorTrans(const Mat &src, Mat &dst, int mirror) {

	Mat tmp(src.rows, src.cols, src.type());

	// 水平镜像变换
	if (mirror == MV_MIRROR_HOR) {
		int cols = src.cols;
		for (int i = 0; i < cols; i++) {
			src.col(cols - i - 1).copyTo(tmp.col(i));
		}
	}

	// 垂直镜像变换
	if (mirror == MV_MIRROR_VER) {
		int rows = src.rows;
		for (int i = 0; i < rows; i++) {
			src.row(rows - i - 1).copyTo(tmp.row(i));
		}
	}

	tmp.copyTo(dst);
}

// 查找十字交叉点
// src:源图像
// pts:输出座标
int MvPub::findCrossPoints(Mat &src, OutputArray o) {

	Mat bak;
	src.copyTo(bak);

	adaptiveThreshold(src, src, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 63, 7);
	//	threshold(src, src, 170, 255, THRESH_BINARY);

	Mat ele0 = getStructuringElement(MORPH_RECT, Size(3, 3));
	erode(src, src, ele0);
	Mat ele1 = getStructuringElement(MORPH_RECT, Size(3, 3));
	dilate(src, src, ele1);

	Mat temp = makeInvTempX(21, 29);
	filter2D(src, src, 8, temp);

	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	findContours(src, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

	// 计算轮廓矩
	vector<Moments> mu(contours.size());
	for (unsigned int i = 0; i < contours.size(); i++) {
		mu[i] = moments(contours[i], false);
	}

	//计算轮廓的质心,过虑不需要点
	cvtColor(src, src, CV_GRAY2RGB);
	cvtColor(bak, bak, CV_GRAY2RGB);

	int cnt = 0;
	vector<Point2f> vo;
	vector<Point2f> mc(contours.size());
	for (unsigned int i = 0; i < contours.size(); i++) {

		mc[i] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
		if (mu[i].m00 > 10 && mu[i].m00 < 400) {
			// 只有符合条件的才打印
			if (mc[i].y < 288 + 8 && mc[i].y > 288 - 8 && mc[i].x < 380) {
				vo.push_back(mc[i]);

				drawXLine(bak, mc[i], CV_RGB(0, 255, 0), 1, 15);
				circle(bak, mc[i], 4, CV_RGB(0, 255, 0), 1);

				Point dispPoint;
				dispPoint.x = mc[i].x;
				dispPoint.y = mc[i].y + 20;
				dispPoint.y -= ((cnt++) % 2) * 20;

				char tmp[64];
				sprintf(tmp, "%0.2f", mc[i].x);
				putText(bak, tmp, dispPoint, 1, 1.2, Scalar(255, 0, 255));

#ifdef HGUI_DEBUG
				imshow("fcp0", bak);
				waitKey(0);
#endif
			}
		}
	}

	Mat mm(vo);
	mm.copyTo(o);

	return 0;
}

// 球在映射
// x0,y0:圆心座标；u,v:源座标
float MvPub::getCircleMapSrcX(int u, int v, float x0, float y0, float r) {

	float xh = u - x0;
	float yi = y0 - v;

	float dx = sqrt(r * r - yi * yi);
	float xk = (x0 + xh * dx / r);

	return xk;
}
float MvPub::getCircleMapSrcY(int u, int v, float x0, float y0, float r) {

	float yh = v - y0;
	float xi = x0 - u;

	float dy = sqrt(r * r - xi * xi);
	float yk = (y0 + yh * dy / r);

	return yk;
}
Point2f MvPub::getCircleMapSrcPoint(int u, int v, float x0, float y0, float r) {

	Point2f p(0.f, 0.f);

	p.x = getCircleMapSrcX(u, v, x0, y0, r);
	p.y = getCircleMapSrcY(u, v, x0, y0, r * 10 / 12);

	return p;
}

void MvPub::getCircleMapSrcPic(Mat &dst, Mat &src, int r) {

	Point2f xy(0.f, 0.f);
	xy.x = src.size().width / 2 + 8;
	xy.y = src.size().height / 2;

	int dstCol = dst.size().width;
	int dstRow = dst.size().height;

	int srcStep = src.step;
	unsigned char* srcData = src.data;
	float p00, p01, p10, p11, pd;
	for (int j = 0; j < dstRow; j++) {
		unsigned char* dstData = dst.data + dst.step * j;
		for (int i = 0; i < dstCol; i++) {
			Point2f srcPoint = getCircleMapSrcPoint(i, j, xy.x, xy.y, r);
			float x = srcPoint.x;
			float y = srcPoint.y;
			int ix = (int) srcPoint.x;
			int iy = (int) srcPoint.y;

			if (x >= dstCol - 1 || y >= dstRow - 1 || x < 0 || y < 0) {
				dstData += 3;
				continue;
			}

			// 4个点合成1个点(座标换成４个点)
			float xd = x - ix, yd = y - iy;
			float xdn = 1 + ix - x, ydn = 1 + iy - y;
			int cp = iy * srcStep + ix * 3;

			p00 = srcData[cp] * xdn;
			p01 = srcData[cp + 3] * xd;
			pd = (p00 + p01) * ydn;
			p10 = srcData[cp + srcStep] * xdn;
			p11 = srcData[cp + srcStep + 3] * xd;
			pd += (p10 + p11) * yd;
			*dstData = pd; // 目标点数据R
			dstData++;

			cp++;
			p00 = srcData[cp] * xdn;
			p01 = srcData[cp + 3] * xd;
			pd = (p00 + p01) * ydn;
			p10 = srcData[cp + srcStep] * xdn;
			p11 = srcData[cp + srcStep + 3] * xd;
			pd += (p10 + p11) * yd;
			*dstData = pd; // 目标点数据G
			dstData++;

			cp++;
			p00 = srcData[cp] * xdn;
			p01 = srcData[cp + 3] * (xd);
			pd = (p00 + p01) * ydn;
			p10 = srcData[cp + srcStep] * xdn;
			p11 = srcData[cp + srcStep + 3] * xd;
			pd += (p10 + p11) * yd;
			*dstData = pd; // 目标点数据B
			dstData++;
		}
	}
}

int MvPub::threshholdEx(Mat &src, int thresholdMode, int thresholdValue, int blocksize, int offset) {

	cvtColor(src, src, CV_RGB2GRAY);
	if (thresholdMode == MV_THRESHOLD_ADAPTIVE) {
		GaussianBlur(src, src, Size(3, 3), 0, 0);
		adaptiveThreshold(src, src, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, blocksize, offset);
	}
	if (thresholdMode == MV_THRESHOLD_FIX) {
		GaussianBlur(src, src, Size(7, 7), 0, 0);
		threshold(src, src, thresholdValue, 255, THRESH_BINARY);
	}

	return 0;
}

// １。找最左点；２。找最右点；３。找最上面点；
// 查找点到最近３点形成的夹角近似的点
// 查找棋盘
int MvPub::findChessBoard(Mat &src, OutputArray vertexs, int thresholdValue, int blocksize, int offset) {

	Mat bak;
	src.copyTo(bak);

// 二值化
	cvtColor(src, src, CV_RGB2GRAY);
	adaptiveThreshold(src, src, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, blocksize, offset);

// 找棋盘 47:1~25;45:1~25;43:1~25;41:1~25;39:1~25;37:1~25;35:1~29;33:1~31;31:1~29;29:1~29;27:1~27;25:1~25;23:1~21;21:1~19;19:1~15;
	Size boardSize(6, 4);
	vector<Point2f> ptvec;
	bool found = findChessboardCorners(src, boardSize, ptvec, CV_CALIB_CB_FAST_CHECK);

// 亚像素精度
//	cvtColor(bak, src, CV_RGB2GRAY);
//	find4QuadCornerSubpix(src, ptvec, Size(63, 63));

	if (found != true) {
#ifdef HGUI_DEBUG
		drawChessboardCorners(bak, boardSize, Mat(ptvec), found);
		namedWindow("chessborad", 1);
		imshow("chessborad", bak);
		waitKey(0);
#endif

		cout << "no chess board!" << endl;
		return -1;
	}

#ifdef HGUI_DEBUG
	circle(bak, ptvec[0], 8, Scalar(0, 255, 255), 1, 8, 0);
	circle(bak, ptvec[5], 8, Scalar(0, 255, 255), 1, 8, 0);
	circle(bak, ptvec[18], 8, Scalar(0, 255, 255), 1, 8, 0);
	circle(bak, ptvec[23], 8, Scalar(0, 255, 255), 1, 8, 0);
#endif

	vertexs.create(4, 1, CV_32FC2);
	Point2f *vt = (Point2f*) vertexs.getMat().data;
	vt[0] = ptvec[0];
	vt[1] = ptvec[5];
	vt[2] = ptvec[18];
	vt[3] = ptvec[23];

	return 0;
}

int MvPub::findChessBoardBlock(Mat &src, OutputArray vertexs, int thresholdMode, int thresholdValue, int blocksize,
		int offset) {

#ifdef HGUI_DEBUG
	Mat bak;
	src.copyTo(bak);
#endif

// 二值化
	threshholdEx(src, thresholdMode, thresholdValue, blocksize, offset);

	Mat ele1 = getStructuringElement(MORPH_RECT, Size(5, 5));
	dilate(src, src, ele1);
	Mat ele0 = getStructuringElement(MORPH_RECT, Size(3, 3));
	erode(src, src, ele0);

#ifdef HGUI_DEBUG
	namedWindow("chessborad", 1);
	imshow("chessborad", src);
//	waitKey(0);
#endif

	vector<Point2f> allPoints;

	// 形状
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	findContours(src, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point(0, 0));

	// 计算矩
	vector<Moments> mu(contours.size());
	//计算轮廓的质心
	vector<Point2f> mc(contours.size());

	//转为彩色图
	cvtColor(src, src, CV_GRAY2RGB);
	Scalar color = Scalar(255, 255, 0);
	for (unsigned int i = 0; i < contours.size(); i++) {
		// 计算轮廓矩
		mu[i] = moments(contours[i], false);
		mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);

		// 最小外接圆半径
		Point2f center;
		vector<float> radius(1);
		minEnclosingCircle(Mat(contours[i]), center, radius[0]);
		if (radius[0] > src.size().width / 10 || radius[0] < 10) {
			continue;
		}

		// 面积
		float area = contourArea(Mat(contours[i]));
		if (area < 8 * 8) {
			continue;
		}

		if (area / (CV_PI * radius[0] * radius[0]) > 0.8) {
			continue;
		}
		if (area / (CV_PI * radius[0] * radius[0]) < 0.2) {
			continue;
		}

		// 位置
		if (mc[i].x > src.size().width * 0.9 || mc[i].x < src.size().width * 0.1) {
			continue;
		}
		if (mc[i].y > src.size().height * 0.9 || mc[i].y < src.size().height * 0.1) {
			continue;
		}

		// 不变矩
		double hu[7];
		HuMoments(mu[i], hu);
		if (hu[0] < 0.15 || hu[0] > 0.4 || hu[1] > 0.1 || hu[1] < 0.001 || hu[2] > 0.0005) {
			continue;
		}
//		cout << "hu0:" << hu[0] << " hu1:" << hu[1] << " hu3:" << hu[2] << endl;

		allPoints.push_back(mc[i]);

#ifdef HGUI_DEBUG
		circle(bak, center, radius[0], Scalar(128, 64, 0), 1, 8, 0);
		drawContours(bak, contours, i, color, CV_FILLED, 8, hierarchy, 0, Point(0, 0));
		circle(bak, mc[i], 2, color, -1, 4, 0);

		char temp[64];
		sprintf(temp, "x:%0.2f;y:%0.2f", mc[i].x, mc[i].y);
		putText(bak, temp, mc[i], 1, 1, Scalar(255, 0, 0));

		//画外接矩形
		Rect rr = boundingRect(Mat(contours[i]));
		rectangle(bak, rr, Scalar(255, 128, 0), 1);
		RotatedRect rRect = minAreaRect(Mat(contours[i]));
		Point2f vertices[4];
		rRect.points(vertices); //提取旋转矩形的四个角点
		for (int n = 0; n < 4; n++) {
			line(bak, vertices[n], vertices[(n + 1) % 4], Scalar(0, 255, 0));
		}

		//画外接多边形
		vector<Point> polys;
		approxPolyDP(Mat(contours[i]), polys, 2, true);
		if (polys.size() < 50) {
			polylines(bak, polys, true, Scalar(255, 80, 180), 1);
		}
#endif
	}

#ifdef HGUI_DEBUG
	imshow("chessborad", bak);
//	waitKey(0);
#endif

	return 0;
}

// 透视变换，输出透视变换后的图像
// 按输出图像座标求输入图像座标
int MvPub::perspectiveInvTransform(Mat &src, InputArray srcCorner, InputArray dstCorner, int interpolation,
		OutputArray img) {

// 1.获取变换函数
	Mat transform = getPerspectiveTransform(dstCorner, srcCorner); // 倒着变换,技巧＊＊

// 2.获取映射点座标
	int dstRow = src.size().height, dstCol = src.size().width;
	Mat dst(dstRow, dstCol, CV_8UC3, Scalar(0, 0, 0));
	vector<Point2f> ponits, transPoints;
	for (int i = 0; i < dstRow; i++) {
		for (int j = 0; j < dstCol; j++) {
			ponits.push_back(Point2f(j, i));
		}
	}
	perspectiveTransform(ponits, transPoints, transform); // transPoints:原图，ponits：目标图座标

	int count = 0;
	float p00, p01, p10, p11, pd;
	int srcStep = src.step;
	unsigned char* srcData = src.data;
	for (int j = 0; j < dstRow; j++) {
		unsigned char *dstData = dst.ptr<unsigned char>(j);
		for (int i = 0; i < dstCol; i++) {
			float y = transPoints[count].y;
			float x = transPoints[count].x;
			count++;

			if (interpolation != true) {
				x = (int) x;
				y = (int) y;
			}
			if (x > dstCol - 1 || y > dstRow - 1 || x < 0 || y < 0) {
				dstData += 3;
				continue;
			}

			int ix = (int) x;
			int iy = (int) y;

			// 4个点合成1个点(座标换成４个点)
			float xd = x - ix, yd = y - iy;
			float xdn = 1 + ix - x, ydn = 1 + iy - y;
			int cp = iy * srcStep + ix * 3;

			p00 = srcData[cp] * xdn;
			p01 = srcData[cp + 3] * xd;
			pd = (p00 + p01) * ydn;
			p10 = srcData[cp + srcStep] * xdn;
			p11 = srcData[cp + srcStep + 3] * xd;
			pd += (p10 + p11) * yd;
			*dstData = pd; // 目标点数据R
			dstData++;

			cp++;
			p00 = srcData[cp] * xdn;
			p01 = srcData[cp + 3] * xd;
			pd = (p00 + p01) * ydn;
			p10 = srcData[cp + srcStep] * xdn;
			p11 = srcData[cp + srcStep + 3] * xd;
			pd += (p10 + p11) * yd;
			*dstData = pd; // 目标点数据G
			dstData++;

			cp++;
			p00 = srcData[cp] * xdn;
			p01 = srcData[cp + 3] * (xd);
			pd = (p00 + p01) * ydn;
			p10 = srcData[cp + srcStep] * xdn;
			p11 = srcData[cp + srcStep + 3] * xd;
			pd += (p10 + p11) * yd;
			*dstData = pd; // 目标点数据B
			dstData++;
		}
	}

#ifdef HGUI_DEBUG
	namedWindow("test", 1);
	imshow("test", dst);
	waitKey(0);
#endif

	return 0;
}

// 透视变换，输出透视变换前的座标
// 按输出图像座标求输入图像座标
int MvPub::perspectiveInvTransform(Size imgSize, InputArray srcCorner, InputArray dstCorner, OutputArray dstPts) {

	// 1.获取变换函数
	Mat transform = getPerspectiveTransform(dstCorner, srcCorner); // 倒着变换,技巧＊＊

	// 2.获取映射点座标
	int dstRow = imgSize.height, dstCol = imgSize.width;
	vector<Point2f> ponits, transPoints;
	for (int i = 0; i < dstRow; i++) {
		for (int j = 0; j < dstCol; j++) {
			ponits.push_back(Point2f(j, i));
		}
	}
	perspectiveTransform(ponits, transPoints, transform); // transPoints:原图，ponits：目标图座标

	// 转换为原图相似座标系
	dstPts.create(dstRow, dstCol, CV_32FC2);
	Mat outData = dstPts.getMat();
	for (int j = 0; j < dstRow; j++) {
		Point2f *d = outData.ptr<Point2f>(j);
		for (int i = 0; i < dstCol; i++) {
			*d = transPoints[0, j * dstCol + i];
			d++;
		}
	}

	return 0;
}

// 透视变换，把输入座标变换后输出透视变换后的座标
int MvPub::perspectivePosTransform(InputArray inPts, InputArray srcCorner, InputArray dstCorner, OutputArray dstPts) {

	// 1.获取变换函数
	Mat transform = getPerspectiveTransform(srcCorner, dstCorner);

	// 2.获取映射点座标
	Mat mtPts = inPts.getMat();
	perspectiveTransform(mtPts, dstPts, transform); // mtPts:原，outPts：目标座标

	return 0;
}

// 按比例生成梯形４个角的座标(中心对齐)
int MvPub::makePerspectiveCorners(float horUp, float horDown, float ver, Point2f posCenterDown, OutputArray corner) {

	corner.create(Size(1, 4), CV_32FC2);
	Point2f *dps = (Point2f *) corner.getMat().data;

	float x00 = posCenterDown.x - horUp / 2;
	float y00 = posCenterDown.y - ver;
	float x01 = posCenterDown.x + horUp / 2;
	float y01 = y00;
	dps[0] = Point2f(x00, y00); // lu
	dps[1] = Point2f(x01, y01); // ru

	float x10 = posCenterDown.x - horDown / 2;
	float y10 = posCenterDown.y;
	float x11 = posCenterDown.x + horDown / 2;
	float y11 = y10;
	dps[2] = Point2f(x10, y10); // ld
	dps[3] = Point2f(x11, y11); // rd

	return 0;
}

//源与目标图片叠加
//alpha(%)：源图混合比例；thans：源图透明是小阀值
void MvPub::blending(Mat &src, Mat &dst, int alpha, int trans) {

	alpha = alpha * 0x100 / 100;
	int beta = 0x100 - alpha;
	int chl = src.channels();

	for (int j = 0; j < src.rows; j++) {

		unsigned char *ptrSrc = src.ptr<unsigned char>(j);
		unsigned char *ptrDst = dst.ptr<unsigned char>(j);

		for (int i = 0; i < src.cols * chl; i += chl) {
			int sr = ptrSrc[i + 2], sg = ptrSrc[i + 1], sb = ptrSrc[i + 0];
			int dr = ptrDst[i + 2], dg = ptrDst[i + 1], db = ptrDst[i + 0];

			if (sr >= trans || sg >= trans || sb >= trans) {
				ptrDst[i + 2] = (sr * alpha + dr * beta) >> 8;
				ptrDst[i + 1] = (sg * alpha + dg * beta) >> 8;
				ptrDst[i + 0] = (sb * alpha + db * beta) >> 8;
			}
		}
	}
}
